package controllers

import (
    "gouniapp/configs"
    "fmt"
    "net/http"
    "strings"
    "github.com/gin-gonic/gin" 
    "github.com/go-playground/validator/v10" 
    "gorm.io/gorm" 
    "encoding/json"
    "errors"
    "bytes"
    "io"
    "log"
    "time"
    "sync"
    "bufio"
    "github.com/satori/go.uuid"
)
 
// 定义查询参数结构体 
type Query struct {
    Prompt  string `json:"prompt"`
    PollId  string `json:"pollId"`
}
 
type CompletionRequest struct {
    Model         string                 `json:"model"`
    Messages      []Message              `json:"messages"`
    Stream        bool                   `json:"stream"`
    MaxTokens     int                    `json:"max_tokens"`
    Stop          []string               `json:"stop"`
    Temperature   float64                `json:"temperature"`
    TopP          float64                `json:"top_p"`
    TopK          int                    `json:"top_k"`
    FrequencyPenalty float64             `json:"frequency_penalty"`
    N             int                    `json:"n"`
    ResponseFormat ResponseFormat        `json:"response_format"`
}
 
type Message struct {
    Role    string `json:"role"`
    Content string `json:"content"`
}
 
type ResponseFormat struct {
    Type string `json:"type"`
}
 
type ChatCompletion struct {
    ID      string `json:"id"`
    Object  string `json:"object"`
    Created int    `json:"created"`
    Model   string `json:"model"`
    Choices []struct {
        Index int `json:"index"`
        Delta struct {
            Content          string `json:"content"`
            ReasoningContent string `json:"reasoning_content"`
        } `json:"delta"`
        FinishReason string `json:"finish_reason"`
        ContentFilterResults struct {
            Hate struct {
                Filtered bool `json:"filtered"`
            } `json:"hate"`
            SelfHarm struct {
                Filtered bool `json:"filtered"`
            } `json:"self_harm"`
            Sexual struct {
                Filtered bool `json:"filtered"`
            } `json:"sexual"`
            Violence struct {
                Filtered bool `json:"filtered"`
            } `json:"violence"`
        } `json:"content_filter_results"`
    } `json:"choices"`
    SystemFingerprint string `json:"system_fingerprint"`
    Usage struct {
        PromptTokens     int `json:"prompt_tokens"`
        CompletionTokens int `json:"completion_tokens"`
        TotalTokens      int `json:"total_tokens"`
    } `json:"usage"`
}
 
type ChatCompletionChunk struct {
    ID      string `json:"id"`
    Choices []struct {
        Delta struct {
            Content string `json:"content"`
        } `json:"delta"`
        FinishReason string `json:"finish_reason"`
    } `json:"choices"`
    ToolCalls []struct {
        ID   string `json:"id"`
        Type string `json:"type"`
        Function struct {
            Name      string `json:"name"`
            Arguments string `json:"arguments"`
        } `json:"function"`
    } `json:"tool_calls"`
}
 
// 定义任务状态结构体 
type TaskStatus struct {
    Id       string `json:"id"`
    Progress string `json:"progress"`
    Completed bool   `json:"completed"`
    Result   interface{} `json:"result"`
}
 
// 定义全局任务缓存 
var taskCache = &sync.Map{}
 
// AI生成文章 申请key: cloud.siliconflow.cn  
func Blogformai(c *gin.Context) {
    // 解析查询参数 
    var query Query 
    if err := c.ShouldBindJSON(&query); err != nil {
        JsonResponse(c, http.StatusBadRequest, "请求参数无效", nil)
        return 
    }
    apiKey := configs.Config.Sub("AI").GetString("apikey")
    apiModel := configs.Config.Sub("AI").GetString("model")
    if query.Prompt == "" || apiKey == "" || apiModel == "" {
        JsonResponse(c, http.StatusBadRequest, "密钥、模型或提示词为空", nil)
        return 
    }
    // 检查是否为轮询请求 
    if query.PollId != "" {
        handleLongPolling(c, query.PollId) // 处理轮询请求 
        return 
    }
    // 启动新任务 
    uid := uuid.NewV4()
    taskId := uid.String()
    go processAIRequest(taskId, query, apiKey, apiModel)
    // 返回任务 ID 给前端 
    JsonResponse(c, http.StatusOK, "任务已启动", map[string]string{
        "taskId": taskId,
    })
}
 
// 处理轮询请求 
func handleLongPolling(c *gin.Context, pollId string) {
    taskStatus, exists := getTaskStatus(pollId)
    if !exists {
        JsonResponse(c, http.StatusNotFound, "任务不存在", nil)
        return 
    }
    if taskStatus.Completed {
        JsonResponse(c, http.StatusOK, "任务完成", gin.H{
            "completed": true,
            "result":    taskStatus.Result,
        })
        taskCache.Delete(pollId) // 完成后清理缓存 
        return 
    }
    JsonResponse(c, http.StatusOK, "生成中", gin.H{
        "completed": false,
        "progress":  taskStatus.Progress,
    })
}
 
// 处理 AI 请求 
func processAIRequest(taskId string, query Query, apiKey string, apiModel string) {
    // 初始化任务状态 
    initialStatus := &TaskStatus{
        Id:       taskId,
        Progress: "",
        Completed: false,
        Result:   nil,
    }
    taskCache.Store(taskId, initialStatus)  // 必须立即存入缓存 
    reqBodyBytes, err := json.Marshal(&CompletionRequest{
        Model: apiModel,
        Messages: []Message{{
            Role:    "user",
            Content: query.Prompt,
        }},
        Stream:           true,
        MaxTokens:        4096,
        Stop:             []string{"null"},
        Temperature:      0.7,
        TopP:             0.7,
        TopK:             50,
        FrequencyPenalty: 0.5,
        N:                1,
        ResponseFormat:   ResponseFormat{Type: "text"},
    })
    if err != nil {
        log.Printf("Failed to marshal request body: %v", err)
        markTaskComplete(taskId)
        return 
    }
    // 发送请求并处理流式响应 
    client := &http.Client{
        Timeout: time.Second * 60,
    }
    req, err := http.NewRequest("POST", "https://api.siliconflow.cn/v1/chat/completions",  bytes.NewBuffer(reqBodyBytes))
    if err != nil {
        log.Printf("Failed to create request: %v", err)
        markTaskComplete(taskId)
        return 
    }
    req.Header.Set("Accept", "text/event-stream")
    req.Header.Set("Authorization", "Bearer "+apiKey)
    req.Header.Set("Content-Type", "application/json")
    resp, err := client.Do(req)
    if err != nil {
        log.Printf("Failed to send request: %v", err)
        markTaskComplete(taskId)
        return 
    }
    defer resp.Body.Close()
    if resp.StatusCode != http.StatusOK {
        log.Printf("API request failed with status code %d", resp.StatusCode)
        markTaskComplete(taskId)
        return 
    }
    // 读取并存储中间结果 
    reader := bufio.NewReader(resp.Body)
    for {
        line, err := reader.ReadBytes('\n')
        if err != nil {
            if err == io.EOF {
                break 
            }
            log.Printf("Error reading response stream: %v", err)
            break 
        }
        // 处理SSE格式 
        if bytes.HasPrefix(line, []byte("data: ")) {
            // 提取有效JSON部分 
            jsonData := bytes.TrimPrefix(line, []byte("data: "))
            jsonData = bytes.TrimSpace(jsonData)
            // 检查结束标记 
            if bytes.Equal(jsonData, []byte("[DONE]")) {
                break 
            }
            // 空数据跳过 
            if len(jsonData) == 0 {
                continue 
            }
            // 解析JSON 
            var chunk ChatCompletionChunk 
            if err := json.Unmarshal(jsonData, &chunk); err != nil {
                log.Printf("Error parsing JSON chunk: %v", err)
                continue 
            }
            // 更新任务状态 
            updateTaskStatus(taskId, chunk)
            // 检查是否完成 
            if chunk.Choices[0].FinishReason != "" {
                break 
            }
        }
    }
    // 标记任务完成 
    markTaskComplete(taskId)
}
 
// 更新任务状态 
func updateTaskStatus(taskId string, chunk ChatCompletionChunk) {
    taskStatus, exists := taskCache.Load(taskId)
    if !exists {
        taskStatus = &TaskStatus{
            Id:       taskId,
            Progress: "",
            Completed: false,
            Result:   nil,
        }
        
        taskCache.Store(taskId, taskStatus)
    }
    currentStatus := taskStatus.(*TaskStatus)
    // 更新进度 
    currentStatus.Progress += chunk.Choices[0].Delta.Content 
    // 检查是否完成 
    if chunk.Choices[0].FinishReason != "" {
        currentStatus.Completed = true 
        currentStatus.Result = currentStatus.Progress 
        log.Printf("任务 %s 已完成，结果：%s", taskId, currentStatus.Result)
    }
}
 
// 标记任务完成 
func markTaskComplete(taskId string) {
    // 设置删除计时器（5分钟后清理）
    time.AfterFunc(5*time.Minute, func() {
        taskCache.Delete(taskId)
    })
    // 立即标记为完成（以防后续逻辑需要）
    taskStatus, exists := taskCache.Load(taskId)
    if exists {
        taskStatus.(*TaskStatus).Completed = true 
        log.Printf("任务 %s 已标记为完成", taskId)
    }
}
 
// 获取任务状态 
func getTaskStatus(pollId string) (*TaskStatus, bool) {
    taskStatus, exists := taskCache.Load(pollId)
    if !exists {
        return nil, false 
    }
    return taskStatus.(*TaskStatus), true 
}

// 分页获取文章
func GetBlogList(c *gin.Context) {
	var query configs.FormQuery
	if err := c.ShouldBindJSON(&query); err != nil {
		JsonResponse(c, http.StatusBadRequest, "请求参数无效", nil)
		return
	}
	// 限制最大每页数量
	if query.PageSize > 300 {
		query.PageSize = 300
	}
	cx := configs.DB.Model(&configs.Blog{}).Order("is_top DESC, id DESC") // 置顶优先
	if query.Search != "" {
		cx.Where("title LIKE ?", "%"+query.Search+"%")
	}
	var total int64
	if err := cx.Count(&total).Error; err != nil {
		JsonResponse(c, http.StatusInternalServerError, "获取总数失败", nil)
		return
	}
	var blogs []configs.Blog
	if err := cx.Scopes(configs.Paginate(query.Page, query.PageSize)).Find(&blogs).Error; err != nil {
		JsonResponse(c, http.StatusInternalServerError, "获取数据失败", nil)
		return
	}
	JsonResponse(c, http.StatusOK, "获取成功", configs.BlogListResponse{
		Items: blogs,
		Total: total,
	})
}

// 获取单篇文章
func GetBlogDetail(c *gin.Context) {
	id := c.Param("id")
	var blog configs.Blog
	if err := configs.DB.Where("id = ?", id).First(&blog).Error; err != nil {
		JsonResponse(c, http.StatusNotFound, "文章不存在", nil)
		return
	}
	// 增加阅读量
	blog.IsRead += 1
	// 只更新阅读量，不更新创建时间
    if err := configs.DB.Model(&blog).Update("is_read", blog.IsRead).Error; err != nil {
        JsonResponse(c, http.StatusInternalServerError, "更新阅读量失败", nil)
        return
    }
	JsonResponse(c, http.StatusOK, "获取成功", blog)
}

// 创建文章
func CreateBlog(c *gin.Context) {
	var blog configs.Blog
	if err := c.ShouldBindJSON(&blog); err != nil {
	    fmt.Println(err)
		JsonResponse(c, http.StatusBadRequest, "请求数据无效", nil)
		return
	}
	validate := validator.New()
	if err := validate.Struct(blog); err != nil {
		for _, err := range err.(validator.ValidationErrors) {
			fmt.Println("Field:", err.Field(), "Error:", err.Tag())
		}
		JsonResponse(c, http.StatusBadRequest, "数据验证失败", nil)
		return
	}
	tx := configs.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err := tx.Create(&blog).Error; err != nil {
		tx.Rollback()
		if strings.Contains(err.Error(), "Duplicate entry") {
			JsonResponse(c, http.StatusConflict, "标题已存在", nil)
		} else {
			JsonResponse(c, http.StatusInternalServerError, "创建文章失败", nil)
		}
		return
	}
	tx.Commit()
	JsonResponse(c, http.StatusOK, "文章创建成功", blog)
}

// 更新文章
func UpdateBlog(c *gin.Context) {
	var data configs.Blog
	if err := c.ShouldBindJSON(&data); err != nil {
		JsonResponse(c, http.StatusBadRequest, "请求数据格式错误", nil)
		return
	}
	tx := configs.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	updateFields := map[string]interface{}{
		"title":     data.Title,
		"photo":     data.Photo,
		"is_read":   data.IsRead,
		"is_open":   data.IsOpen,
		"is_top":    data.IsTop,
		"multi_file": data.MultiFile,
		"content":   data.Content,
		"cjz":       data.Cjz,
	}
	if err := tx.Model(&configs.Blog{}).Where("id = ?", data.ID).Updates(updateFields).Error; err != nil {
		tx.Rollback()
		if strings.Contains(err.Error(), "Duplicate entry") {
			JsonResponse(c, http.StatusConflict, "标题已存在", nil)
		} else {
			JsonResponse(c, http.StatusInternalServerError, "更新失败", nil)
		}
		return
	}
	tx.Commit()
	JsonResponse(c, http.StatusOK, "更新成功", data)
}

// 删除文章
func DeleteBlog(c *gin.Context) {
    idStr := c.Param("id")
    var id uint
    if _, err := fmt.Sscan(idStr, &id); err != nil {
        JsonResponse(c, http.StatusBadRequest, "无效的文章ID", nil)
        return
    }
    // 开启事务
    err := configs.DB.Transaction(func(tx *gorm.DB) error {
        // 先查询是否存在
        var blog configs.Blog
        if err := tx.First(&blog, id).Error; err != nil {
            return err
        }
        // 执行删除
        return tx.Delete(&blog).Error
    })
    if err != nil {
        if errors.Is(err, gorm.ErrRecordNotFound) {
            JsonResponse(c, http.StatusNotFound, "文章不存在", nil)
        } else {
            JsonResponse(c, http.StatusInternalServerError, "删除失败: "+err.Error(), nil)
        }
        return
    }
    JsonResponse(c, http.StatusOK, "删除成功", nil)
}